package com.wurd.javaagent.premain;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

//打成jar
//包括/test/resources/javaagent/META-INF/MANIFEST.MF
public class PreMainClass {

    //Agent-Class: ...
    public static void agentmain(String agentArgs, Instrumentation inst) {
    }

    ;

    public static void agentmain(String agentArgs) {
    }

    ;

    //Premain-Class: ...
    public static void premain(String agentArgs) {
        System.out.println("agentArgs : " + agentArgs);
    }

    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("agentArgs(Instrumentation) : " + agentArgs);
        inst.addTransformer(new DefineTransformer1(), true);
    }

    static class DefineTransformer1 implements ClassFileTransformer {

        @Override
        public byte[] transform(ClassLoader loader, String className,
                                Class<?> classBeingRedefined,
                                ProtectionDomain protectionDomain,
                                byte[] classfileBuffer) {
            try {
                if (loader != null) {
                    final ClassPool classPool = ClassPool.getDefault();
                    final CtClass clazz = classPool.get(className.replace("/", "."));
                    Object annotation = clazz.getAnnotation(WurdAspect.class);
                    if (annotation != null) {
                        CtMethod[] methods = clazz.getDeclaredMethods();
                        for (CtMethod method : methods) {
                            Object before = method.getAnnotation(WurdAspectBefore.class);
                            if (before != null) {
                                WurdAspectBefore aspectBefore = (WurdAspectBefore) before;
                                String message = aspectBefore.message();
                                message = "System.out.println(\""+ message +"\");";
                                method.insertBefore(message);
                            }
                        }
                        byte[] byteCode = clazz.toBytecode();
                        clazz.detach();
                        return byteCode;
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return null;
        }
    }

    static class DefineTransformer implements ClassFileTransformer {

        @Override
        public byte[] transform(ClassLoader loader, String className,
                                Class<?> classBeingRedefined,
                                ProtectionDomain protectionDomain,
                                byte[] classfileBuffer) {
            System.out.println("premain load Class:" + className);

            return classfileBuffer;
        }
    }
}
